Skip to content

feat(dm-list-group-avatars): show group DM avatars#816

Open
Just-Insane wants to merge 6 commits into
SableClient:devfrom
Just-Insane:feat/dm-list-group-avatars
Open

feat(dm-list-group-avatars): show group DM avatars#816
Just-Insane wants to merge 6 commits into
SableClient:devfrom
Just-Insane:feat/dm-list-group-avatars

Conversation

@Just-Insane
Copy link
Copy Markdown
Contributor

@Just-Insane Just-Insane commented May 14, 2026

Description

Group DMs now show a composite avatar (up to three member profile pictures stacked) in the sidebar DM list, matching the visual treatment used in other Matrix clients. Avatars are seeded synchronously on mount to prevent a flash of missing images, and the profile-loading lifecycle is cleaned up to prevent stale listeners.

Fixes #

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

AI disclosure:

  • Fully AI generated (explain what all the generated code does in moderate detail).
  • Partially AI assisted (clarify which code was AI assisted and briefly explain what it does).

The component selects up to three non-self member IDs from the room's member list, loads their m.room.member state events for avatar URLs, and lays them out with CSS positioning. Avatars are synchronously seeded from any already-cached member state on mount to avoid a blank flash. The useEffect cleanup removes the member-event listener to prevent a stale closure from updating avatar state after the component unmounts.

@Just-Insane Just-Insane force-pushed the feat/dm-list-group-avatars branch from 04ddec6 to 60e0013 Compare May 14, 2026 19:33
@Just-Insane Just-Insane changed the title feat(dm-list): group DM avatars, iOS autocapitalize fix, and timeline/sort fixes feat(dm-list): show group DM avatars May 14, 2026
@Just-Insane Just-Insane force-pushed the feat/dm-list-group-avatars branch from ecc56ed to 4a45973 Compare May 14, 2026 19:35
Show multiple member avatars for group DMs in the room list and re-sort direct rooms after timeline resets so activity order recovers after limited sync.
@Just-Insane Just-Insane force-pushed the feat/dm-list-group-avatars branch from 76dd0d9 to e33ab68 Compare May 19, 2026 23:27
@Just-Insane Just-Insane changed the title feat(dm-list): show group DM avatars feat(dm-list-group-avatars): show group DM avatars May 19, 2026
@Just-Insane Just-Insane marked this pull request as ready for review May 19, 2026 23:39
@Just-Insane Just-Insane requested review from 7w1 and hazre as code owners May 19, 2026 23:39
Copilot AI review requested due to automatic review settings May 19, 2026 23:39
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds composite (multi-member) avatars for group DMs in the Direct Messages room list, and tightens the DM list sorting trigger behavior so recent activity is reflected promptly without stale listeners/flash states.

Changes:

  • Render a 2–3 member “triangle stack” avatar for group DMs in the room nav list (RoomNavItem + room-nav styles).
  • Seed group-DM member avatar data synchronously from existing room state and add safe async cancellation (useGroupDMMembers).
  • Improve DM list re-sorting by listening for TimelineReset and forcing an initial re-sort on mount (Direct.tsx).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/app/pages/client/direct/Direct.tsx Updates header layout, adjusts listener lifecycle for DM activity sorting, and refactors layout around the sidebar resizer.
src/app/hooks/useGroupDMMembers.ts Adds synchronous initial seeding from local room state and cancellation to avoid post-unmount updates; makes room optional.
src/app/features/room-nav/styles.css.ts Adds CSS for group-DM composite avatar layout in the room nav.
src/app/features/room-nav/RoomNavItem.tsx Uses useGroupDMMembers and renders the composite avatar for group DMs.
.changeset/dm-list-group-avatars.md Declares a minor changeset entry for the new feature.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +272 to +279
<Box
shrink="No"
style={{
width: isMobile ? '100%' : toRem(curWidth),
}}
>
<PageNav>
<DirectHeader hideText={hideText} />
Comment thread src/app/pages/client/direct/Direct.tsx Outdated
return (
<VirtualTile
virtualItem={vItem}
key={vItem.index}
Comment thread src/app/hooks/useGroupDMMembers.ts Outdated
useEffect(() => {
let cancelled = false;
if (!room) {
setMembers([]);
Comment on lines +429 to +433
<Box as="span" grow="Yes" alignItems="Center" style={hideTextStyling(hideText)}>
{isGroupDM && showAvatar && groupMembers.length > 1 ? (
// Group DM: triangle layout of mini avatars
<div className={css.GroupAvatarRow}>
{groupMembers.map((member) => {
- Use stable roomId as VirtualTile key (prevents stale state when sort order changes)
- Add getItemKey to virtualizer so it tracks items by roomId not index
- Move SidebarResizer inside the position:relative Box so it positions correctly
- Guard setMembers([]) with functional update to skip re-render when already empty
- Scale GroupAvatarRow to 32px in hideText mode to match Avatar size='300' slot
…xt mode

Add GroupAvatarRowHideText (32px) and GroupAvatarMiniHideText (18px) CSS classes
for the icon-only sidebar mode. Previously only the container was scaled to 32px
via inline style while mini avatars remained at 14px, leaving them sparse and
misaligned. Now both container and minis use proportionally larger sizes.

Addresses Copilot review comment on SableClient#816.
Just-Insane added a commit to Just-Insane/Sable that referenced this pull request May 20, 2026
- fix(phantom-unreads): restrict badge suppression to SUPPRESSABLE_SENT_EVENT_TYPES
  (m.room.message / m.room.encrypted / m.sticker) and pass room+userId to
  isNotificationEvent to prevent state events from clearing badges (SableClient#883)

- fix(dm-list-group-avatars): add GroupAvatarRowHideText/GroupAvatarMiniHideText
  CSS classes (32px/18px) so composite DM avatars scale properly in icon-only
  sidebar mode instead of leaving 14px minis in a 32px container (SableClient#816)

- fix(media-cache): catch downloadMedia errors in openMediaInNewTab so a failed
  network response does not become an unhandled promise rejection (SableClient#870)

- fix(media-cache): restore touchCacheEntry LRU tracking in useBlobCache.ts that
  was dropped during merge; cache hits now update the access timestamp so
  frequently-used entries are not prematurely evicted (SableClient#870)

- fix(media-cache): restore SVG_BLOB_CACHE_MAX eviction cap and non-SVG URL
  fast-path in AvatarImage.useProcessedAvatarSrc that were dropped during merge;
  prevents unbounded memory growth and avoids a redundant fetch for every
  .png/.jpg/.gif/.webp avatar (SableClient#870)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants